<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow-IPC: ipc::util::sync_io Namespace Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow-IPC<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow-IPC project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="namespaceipc.html">ipc</a></li><li class="navelem"><a class="el" href="namespaceipc_1_1util.html">util</a></li><li class="navelem"><a class="el" href="namespaceipc_1_1util_1_1sync__io.html">sync_io</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="summary">
<a href="#nested-classes">Classes</a> &#124;
<a href="#typedef-members">Typedefs</a> &#124;
<a href="#func-members">Functions</a>  </div>
  <div class="headertitle"><div class="title">ipc::util::sync_io Namespace Reference</div></div>
</div><!--header-->
<div class="contents">

<p>Contains common code, as well as important explanatory documentation in the following text, for the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern used in <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> and <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> to provide fine-tuned control over integrating asynchronous Flow-IPC activities into the user's event loop.  
<a href="namespaceipc_1_1util_1_1sync__io.html#details">More...</a></p>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="nested-classes" name="nested-classes"></a>
Classes</h2></td></tr>
<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">class &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">Asio_waitable_native_handle</a></td></tr>
<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Useful if using the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern within a user event loop built on boost.asio (optionally with flow.async help), an object of this class wraps a non-null <a class="el" href="structipc_1_1util_1_1Native__handle.html" title="A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.">Native_handle</a> and allows one to use <code>.async_wait()</code> to perform event waiting on behalf of any <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-implementing <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> or <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> object.  <a href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html#details">More...</a><br /></td></tr>
<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">class &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html">Timer_event_emitter</a></td></tr>
<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">An object of this type, used internally to implement <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern objects that require timer events, starts a thread dedicated exclusively to running timer waits on the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> object's behalf, so that when such a timer fires, it emits a pipe-readable event to be detected by the user's event loop, which it then reports to <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> object.  <a href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html#details">More...</a><br /></td></tr>
<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="typedef-members" name="typedef-members"></a>
Typedefs</h2></td></tr>
<tr class="memitem:ac6973c71fc70c6d867b0f2255c642532"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">Task_ptr</a> = boost::shared_ptr&lt; <a class="el" href="namespaceipc_1_1util.html#a31e67d3a017477a04b313927e2f2c733">Task</a> &gt;</td></tr>
<tr class="memdesc:ac6973c71fc70c6d867b0f2255c642532"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for ref-counted pointer to a <code>Function&lt;&gt;</code> that takes no arguments and returns nothing; in particular used for <code>on_active_ev_func</code> arg of <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">sync_io::Event_wait_func</a>.  <a href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">More...</a><br /></td></tr>
<tr class="separator:ac6973c71fc70c6d867b0f2255c642532"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:aa0b9a3cc6bdc7dedbef4f9e06851aa24"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24">Event_wait_func</a> = <a class="el" href="namespaceipc.html#aa455c7f045059736578ca275fc1a851f">Function</a>&lt; void(<a class="el" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">Asio_waitable_native_handle</a> *hndl_of_interest, bool ev_of_interest_snd_else_rcv, <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">Task_ptr</a> &amp;&amp;on_active_ev_func)&gt;</td></tr>
<tr class="memdesc:aa0b9a3cc6bdc7dedbef4f9e06851aa24"><td class="mdescLeft">&#160;</td><td class="mdescRight">In <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern, concrete type storing user-supplied function invoked by pattern-implementing <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> and <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> object to indicate interest in an I/O status event (writable, readable) for a particular <a class="el" href="structipc_1_1util_1_1Native__handle.html" title="A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.">Native_handle</a>.  <a href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24">More...</a><br /></td></tr>
<tr class="separator:aa0b9a3cc6bdc7dedbef4f9e06851aa24"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="func-members" name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:adef3ac3be5570b22492dd9214b4cb3da"><td class="memItemLeft" align="right" valign="top">std::ostream &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="namespaceipc_1_1util_1_1sync__io.html#adef3ac3be5570b22492dd9214b4cb3da">operator&lt;&lt;</a> (std::ostream &amp;os, const <a class="el" href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html">Timer_event_emitter</a> &amp;val)</td></tr>
<tr class="memdesc:adef3ac3be5570b22492dd9214b4cb3da"><td class="mdescLeft">&#160;</td><td class="mdescRight">Prints string representation of the given <code><a class="el" href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html" title="An object of this type, used internally to implement sync_io-pattern objects that require timer event...">Timer_event_emitter</a></code> to the given <code>ostream</code>.  <a href="namespaceipc_1_1util_1_1sync__io.html#adef3ac3be5570b22492dd9214b4cb3da">More...</a><br /></td></tr>
<tr class="separator:adef3ac3be5570b22492dd9214b4cb3da"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><p >Contains common code, as well as important explanatory documentation in the following text, for the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern used in <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> and <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> to provide fine-tuned control over integrating asynchronous Flow-IPC activities into the user's event loop. </p>
<h3>What's all this, then?</h3>
<p >You may notice that for ~every class/class template <code>X</code> in this library that provides 1+ <code>X::async_*(..., F)</code> method(s), where <code>F()</code> is a completion handler for an async operation, there exists also &ndash; in a sub-namespace named <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> &ndash; a similar-looking type <code>sync_io::X</code>.</p>
<dl class="section note"><dt>Note</dt><dd>At times, generally in <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> and class template <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">ipc::transport::struc::Channel</a> specifically, async ops don't necessarily use <code>async_*</code> naming, but the point remains that: an operation occurs in some sense in the background, and then a <em>handler</em> function, given as an arg, is called when the operation is completed. Neverthelss for this discussion we will often take the case of, indeed, an operation named <code>X::async_*(..., F)</code>, with <code>F()</code> a one-off completion handler. It's the basic, most mainstream pattern.</dd></dl>
<p>Long story short, all else being equal, we would recommend the use of <code>X</code> over <code>sync_io::X</code>: it is easier (in most cases), less error-prone, and delivers similar performance &ndash; quite possibly even better (due to automatic parallelization albeit at the cost of mandatory context-switching). However <code>sync_io::X</code> does exist for a good reason, at least for some important <code>X</code>es, and in an advanced, highly peformance-sensitive application it may be worth considering switching to the <em>direct</em> use of <code>sync_io::X</code>. For what it is worth, internally <code>X</code> is usually written in terms of <code>sync_io::X</code>; the latter is essentially the core logic, while the former provides auto-parallelization and a simpler interface.</p>
<dl class="section note"><dt>Note</dt><dd>For this reason comments sometimes refer to a <code>sync_io::X</code> <em>core</em>: where the basic <code>X</code>-ish capabalities and data live. The <em>async-I/O</em> <code>X</code> is then often built around a <code>sync_io::X</code> core. Because of this it is usually easy, and fast, to convert a <code>sync_io::X</code> into an <code>X</code> &ndash; via a move-like ctor called <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-core <em>adopting ctor</em>. Additionally, <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">ipc::transport::Channel</a> template &ndash; which bundles local peer objects of 1-2 IPC pipes &ndash; can bundle <em>either</em> async-I/O peer objects <em>or</em> <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> peer objects, and one can always convert the latter to the former by calling <code>x.async_io_obj()</code>.</dd>
<dd>
In cases where performance is not a real concern, such as for the assumed-rare <a class="el" href="classipc_1_1session_1_1Session__server.html#a13887cd64912bb5f5675e2817ff8435f" title="Asynchronously awaits for an opposing Client_session to request session establishment and calls on_do...">ipc::session::Session_server::async_accept()</a> operations, internally <code>sync_io::X</code> may actually be written in terms of <code>X</code> instead... but we digress. Either way it is a black box.</dd></dl>
<p>Some examples of <code>X</code>es that have <code>sync_io::X</code> counterparts:</p><ul>
<li>core-layer <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">transport::Native_socket_stream</a> (including its <code>async_receive_*()</code>, and the handler-less &ndash; but nevertheless potentially asynchronous &ndash; <code>send_*()</code>) and all other <code>Blob_sender</code>, <code>Blob_receiver</code>, <code>Native_handle_sender</code>, <code>Native_handle_receiver</code> concept impls including the bundling <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>;</li>
<li>structured-layer <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">ipc::transport::struc::Channel</a>;</li>
<li><a class="el" href="namespaceipc_1_1session.html#a77d8fda00e1e17f595a6a5d4c44375e7" title="A vanilla Client_session with no optional capabilities.">session::Client_session</a> (with its channel-accept and error handlers) and <a class="el" href="classipc_1_1session_1_1Session__server.html" title="To be instantiated typically once in a given process, an object of this type asynchronously listens f...">session::Session_server</a> (ditto, plus with its <code>async_accept()</code>);<ul>
<li>all their <a class="el" href="namespaceipc_1_1session_1_1shm.html" title="ipc::session sub-namespace that groups together facilities for SHM-backed sessions,...">session::shm</a> counterparts.</li>
</ul>
</li>
</ul>
<h3>The async-I/O (default) pattern</h3>
<p >Consider <code>X</code> &ndash; take for example <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">transport::Native_socket_stream</a> &ndash; and a particular async operation &ndash; take, e.g., <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html#ac5572c8165e25f106f18d327c07d1c3f" title="Implements Blob_receiver API per contract.">transport::Native_socket_stream::async_receive_blob()</a>.</p>
<p >When <code>x.async_receive_blob(..., F)</code> is invoked, <code>F()</code> is the user-specified completion handler, while ... specifies details about the operation, in this case the target buffer where to write data. It works as follows: <code>x</code> attempts to perform the operation (in this case receive a single in-message as soon as it becomes available which may or may not be instant); and once it has suceeded, it invokes <code>F(...)</code> (where ... indicates results, usually at least an <code>Error_code</code>) from <em>an unspecified thread</em> that is not the user's calling thread (call it thread U, where <code>x.async_*()</code> was called). Even if the op completes immediately, <code>x.async_*()</code> will never invoke <code>F()</code> synchronously; always from the <em>unspecified thread</em>.</p>
<p >That's great, but what does really happen? Answer: <code>x</code>, usually at construction, invisibly, starts a separate thread (technically it could be co-using a thread with other objects; but in reality as of this writing each object really starts a thread). An async operation might complete synchronously (perhaps a message is available in a kernel receive buffer and is therefore immediately, internally, received inside <code>x.async_receive_blob()</code> body); or it might occur in the background and involve (internally) async waiting of native-handle readability &ndash; possibly even more threads might start (internally) to get things to work. <em>Either</em> way, there is that thread &ndash; call it thread W &ndash; where <em>at least</em> the completion handler <code>F()</code> will be called.</p>
<p >(If <code>x</code> is destroyed before this has a chance to happen, the <code>x</code> destructor shall &ndash; last-thing &ndash; invoke <code>F()</code>, passing it the special operation-aborted <code>Error_code</code>. That is the case for one-off async-ops like that one. There are also variations such as the completion handlers of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">transport::struc::Channel</a>, but the key point &ndash; that work happens in the background, in the object-created own thread W, and user-supplied handlers are run from thread W &ndash; remains the same. Another variation is async-ops that don't require a completion handler; for example <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html#a415febd76ee222c81d59d2bcfa9c01bc" title="Implements Blob_sender API per contract.">transport::Native_socket_stream::send_blob()</a> may perform work in the background upon encountering would-block conditions internally &ndash; and this again occurs in thread W &ndash; but there is no completion handler to invoke.)</p>
<p >What is the user supposed to do with an async-op like this? In practice we tend to think of this in terms of 2 basic possiblities for how the user's own event loop might be organized.</p><ul>
<li>Proactor pattern: This is what boost.asio uses, what flow.async facilitates further, and what we generally recommend all else being equal. We won't describe it here in detail, but integrating such a loop with this async-I/O pattern in Flow-IPC is quite simple:<ol type="1">
<li>Call <code>x.async_*(..., F)</code> as explained above.</li>
<li>As <code>F()</code> supply a short wrapper that will place the true handling of the event onto the same event loop &ndash; thread U (though multiple such threads might be in use alternatively) &ndash; where you invoked <code>x.async_*(F)</code>. For example:</li>
</ol>
</li>
</ul>
<div class="fragment"><div class="line">  ...</div>
<div class="line">  m_my_asio_loop.post([t]() { start_async_op(); }</div>
<div class="line">  ...</div>
<div class="line">void start_async_op()</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are in thread U.</span></div>
<div class="line">  x.async_receive_blob(..., [<span class="keyword">this</span>](<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code, <span class="keywordtype">size_t</span> sz)</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// We are in &quot;unspecified thread&quot; W.</span></div>
<div class="line">    m_my_asio_loop.post([<span class="keyword">this</span>, err_code, sz]() { on_async_op_done(err_code, sz); }</div>
<div class="line">  }</div>
<div class="line">}</div>
<div class="line"><span class="keywordtype">void</span> on_async_op_done(<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code, <span class="keywordtype">size_t</span> sz)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are in thread U.</span></div>
<div class="line">  <span class="comment">// ...handle it....</span></div>
<div class="line">}</div>
<div class="ttc" id="anamespaceipc_html_aa3192e586cc45d3e7c22463bf2760f89"><div class="ttname"><a href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">ipc::Error_code</a></div><div class="ttdeci">flow::Error_code Error_code</div><div class="ttdoc">Short-hand for flow::Error_code which is very common.</div><div class="ttdef"><b>Definition:</b> <a href="common_8hpp_source.html#l00298">common.hpp:298</a></div></div>
</div><!-- fragment --><p >Alternatively:</p><ul>
<li>Reactor pattern: Usually built on top of an OS-supplied blocking polling method of some kind &ndash; in POSIX nowadays usually at least <code>poll()</code>, in Linux possibly using the more advanced <code>epoll_*()</code> &ndash; which centers on an "FD-set" (native handle set), where one describes <code><a class="el" href="structipc_1_1util_1_1Native__handle.html" title="A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.">Native_handle</a></code>s (FDs) and the events one awaits (readable, writable) for each; and in each event loop iteration one runs a poll-wait operation (like <code>poll()</code> or <code>epoll_wait()</code>). This blocks until 1 or more events-of-interest are active; then wakes up and reports which ones they were. User code then synchronously invokes handling for each event of interest; such handling might modify the events-of-interest set, etc., until all such work is done, and the next poll-wait op executes. Thus in the reactor pattern methods like <code>on_async_op_done()</code> are invoked in a flow-control setup inverted versus the proactor pattern; but ultimately they're both doing the same thing. To integrate such a loop with this async-I/O pattern in Flow-IPC, a little extra work is required:<ul>
<li>Sometimes event-loop libraries provide this as a built-in feature: a <em>task queue</em>. So a facility similar to <code>post()</code> above is supplied. Hence the code above would be adapted to a reactor-pattern loop and end up fairly similar: In <code>F()</code> do some equivalent to the <code>post()</code> in the snippet above. Internally it'll set up some "interrupter" handle in the central <code>[e]poll*()</code> handle-set and cause &ndash; from thread W &ndash; for thread U's poll-wait to wake up. Otherwise:</li>
<li>This task-queue facility can be written with relatively little difficulty. Essentially it involves a simple IPC mechanism, perhaps an anonymous pipe, through which thread-W-invoked <code>F()</code>s can inform the thread-U poll-wait that it must wake up and handle events, among any others that the poll-wait covers.</li>
</ul>
</li>
</ul>
<p >So that's the async-I/O (default) pattern in Flow-IPC. Generally it is easy to work with &ndash; especially in a proactor-pattern event loop, but otherwise also not hard. It cleanly separates Flow-IPC's internal needs from the rest of the application's: Flow-IPC needs to do background work? It takes care of its own needs: it starts and ends threads without your participation. Moreover this may well help performance of the user's own event loop: Flow-IPC's cycles are mostly spent in separate threads, reducing the length of your loop's single iteration and thus helping reduce your latency. The processors' context-switching is automatic and usually efficient; and it automatically makes use of multiple hardware cores.</p>
<h3>Rationale for the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern</h3>
<p >So why might the default pattern described above be insufficient? A detailed study of this is outside our scope here; but basically it is a matter of control. The way it starts threads, in a way that cannot be specified by you (the user), and switches between them may be helpful in 95% of cases; but some applications want complete control of any such thing. For instance suppose I'd like to start with doing all that background work of <code>Native_socket_stream::async_receive_blob()</code> directly in thread U. It should be possible, right? Whatever events it waits on &ndash; in reality, internally, principally it waits for readability of a Unix domain socket &ndash; I could just wait-on in my own thread-U <code>epoll_wait()</code>. When an active event is detected, I could do the resulting non-blocking-reads &ndash; that normally would be done in the background thread W &ndash; directly after the poll-wait.</p>
<p >Maybe that would be good, reducing context-switching overhead. Or maybe it wouldn't be good, as a big fat loop iteration could cause latency in serving the next batch of work. If so, and I <em>did</em> want to do some of the work in some other thread for parallelization, maybe I want to share that other thread with some other processing. Or... or.... Point is: perhaps I want to explicitly structure what threads do what, whether or not I want multi-threaded processing.</p>
<p >If that is the case, then the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern will serve that need. In this pattern, for example in <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html" title="Implements both sync_io::Native_handle_sender and sync_io::Native_handle_receiver concepts by using a...">transport::sync_io::Native_socket_stream</a>, you'll notice completion handlers are still used as part of the API. However, they are <em>never</em> invoked in the background: <em>you</em> call into a <code>sync_io::X</code> API, and it might <em>synchronously only</em> and at very specific points invoke a completion handler <code>F()</code> that you supplied it earlier.</p>
<p >We'll get into details below, but to summarize how this is integrated with the 2 above-covered user event loop patterns:</p><ul>
<li>Proactor pattern: The <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern in Flow-IPC has first-class support for a boost.asio event loop on the user's part. So &ndash; basically &ndash; if you've got a <code>boost::asio::io_context E</code> (<code>flow::util::Task_engine E</code>) <code>run()</code>ning over 1+ threads U, then <code>sync_io::X</code> shall give you boost.asio <code>descriptor</code> objects associated with <code>E</code> and ask <em>you</em> &ndash; yourself, albeit on its behalf &ndash; to perform <code>.async_wait(write, G)</code> or <code>.async_wait(read, G)</code> on those <code>descriptor</code>s; and inform the <code>sync_io::X</code> when they've completed, inside <code>G()</code>. As a result, <code>sync_io::X</code> internals might inform you of the completion of an <code>async_...()</code> op earlier requested by you.</li>
<li>Reactor pattern: If your loop isn't boost.asio-based, then <code>sync_io::X</code> will similarly ask you to perform async-waits on this or that handle for read or write or both, just over a slightly different API &ndash; one conducive to <code>poll()</code>, <code>epoll_ctl()</code>/<code>epoll_wait()</code>, and the like. In short it'll tell you what FD and what event it wants you to wait-on (and again give you function <code>G()</code> to call when it is indeed active).</li>
</ul>
<p >Thus, <em>you</em> control what happens in what thread &ndash; and everything can happen in <em>your</em> single thread, if you so desire. <em>You</em> can create the other threads, arrange necessary synchronization &ndash; including of access to the <code>sync_io::X</code> in question &ndash; as opposed to rely on whatever we've internally designed inside non-<code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> <code>X</code>. <em>You</em> control when a <code>sync_io::X</code> does something. In particular, it is only in a couple of specific <code>sync_io::X::*</code> APIs that a completion handler you gave it can actually be called. <em>If</em> it is called, it is always called synchronously right then and there, not from some unknown background thread.</p>
<h3>So <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing APIs will never start threads?</h3>
<p >Well, they might. In some cases it's an internal need that cannot be avoided. However, when <em>both</em> (1) it can be avoided, <em>and</em> (2) performance could possibly be affected, then correct: Flow-IPC will avoid starting a thread and performing context-switching. If it's immaterial for performance in practice, then it absolutely reserves the right to make background threads, whether for ease of internal implementation or some other reason. And, of course, if there's some blocking API that must be used internally &ndash; and there is simply no choice but to use that API &ndash; then a thread will need to be started behind the scenes. We can't very well block your thread U, so at that point we do what we must.</p>
<p >However, even in <em>that</em> case, a <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> <em>API</em> is still supplied. This may be helpful to more easily integrate with your reactor-pattern event loop. (However, if you have a proactor like boost.asio as your event loop, then in our view it is unlikely to be helpful in that sense. At that point you might as well use the async-I/O alternative API &ndash; unless, again, there is some performance benefit to maintaining greater control of what part of Flow-IPC executes when from what thread.)</p>
<h3>Using the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern: design rationale</h3>
<p >Though it will look different and perhaps complex, it is actually at its core similar to other third-party APIs that require the user to perform async-waits on their behalf. The most well known example of such an API is perhaps OpenSSL. Take <code>SSL_read()</code> &ndash; quite similar in spirit to <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern <code>x.async_read_blob()</code>. When invoked, barring connection-hosing errors, one of 2 things will happen:</p><ul>
<li>It will succeed and read 1 or more bytes and return this fact ("no error, I have read N bytes").</li>
<li>It will fail due to would-block, because it either needs the underlying stream socket to be readable, or to be writable. (The latter &ndash; needing writability &ndash; may seem strange for <code>SSL_read()</code>, but it's normal: perhaps the connection is in the middle of a cert negotiation, and at this stage needs to write something <em>out</em> first; and the connection happens to be in such a state as to not be able to write bytes to the kernel send buffer at that moment.) So it will return either:<ul>
<li><code>SSL_ERROR_WANT_READ</code> (meaning, "the underlying stream-socket handle (FD) needs to be readable -- call me
      again after you've *async-waited* successfully on this *event-of-interest*, and I will try again"); or</li>
<li><code>SSL_ERROR_WANT_WRITE</code> (same but needs writability instead).</li>
</ul>
</li>
</ul>
<p >Your application would then internally register interest in FD so-and-so to be readable or writable. Perhaps some <code>SSL_write()</code> would be interested in another such event simultaneously too. So then the next time the event loop came up to the next <code>poll()</code> or <code>epoll_wait()</code>, you'd indeed wait on these registered events. If the <code>SSL_read()</code>-related event-of-interest was indeed returned as active, your program would know that fact, based on its own data structures, and know to try <code>SSL_read()</code> again. That time <code>SSL_read()</code> might succeed; or it might require writability again, or readability this time, and would return <code>SSL_ERROR_WANT_*</code> again. Eventually it'd get what it needs and return success.</p>
<p ><code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern in Flow-IPC is not much different. It is arguably more complex to use, but there are good reasons for it. Namely there are some differences as to our requirements compared to OpenSSL's. To wit:</p><ul>
<li>For a given operation &ndash; whether it's <code>Native_socket_stream::async_receive_blob()</code> or the even more internally complex <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">transport::struc::Channel::expect_msg()</a> &ndash; there will usually be more than 1 event of interest a time, in fact spread out over more than 1 handle (FD) at a time at that. Namely in addition to readability/writability of the underlying low-level trqnsport, there are timer(s) (such as the idle timer &ndash; <code>idle_timer_run()</code>); and <code>struc::Channel</code> can be configured to have 2 in-pipes and thus will be async-waiting on 2 FDs' read events.<ul>
<li>Hence we need to be able to express the desired async-waits to the user in a more flexible way than a simple "can't do it, tell me when my socket is Xable and call me again." We have to communicate an entire set-of-events-of-interest as well as changes in it over time.</li>
</ul>
</li>
<li>OpenSSL is targeted at old-school event loops &ndash; ~all written in the reactor-pattern style. Flow-IPC is meant to be usable by modern proactor-pattern applications <em>and</em> old-school reactor-pattern ones as well. It would be unfortunate, in particular, if a given <code>X</code> is written in the modern handler-based way, while <code>X::sync_io</code> counterpart is just entirely different. In fact, suppose <code>sync_io::X</code> is available; <em>our</em> <code>X</code> internally "wants" to be written around a boost.asio loop <em>and</em> reuse <code>sync_io::X</code> internally as well. So in other words, both aesthetically and practically, an OpenSSL-style old-school API would be a pain to use in a boost.asio-based application (our own async-I/O-pattern classes being a good test case).</li>
</ul>
<p >Therefore the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern is strongly inspired by the boost.asio proactor pattern API. As a corollary it provides special support for the case when the user's event loop <em>is</em> boost.asio-based. If your event loop is old-school, you will lose nothing however &ndash; just don't use that feature.</p>
<h3>Using the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern: how-to</h3>
<p >Take <code>x.async_receive_blob(..., F)</code>. If <code>x</code> is an <code>X</code>, we've already described it. Now let <code>x</code> be a <code>sync_io::X</code>. The good news is initiating the same operation uses <em>almost</em> the exact same signature. It takes the same arguments including a completion handler <code>F()</code> with the exact same signature itself. There is however one difference: if <code>F()</code> takes 1+ args (1st one usually <code>const Error_code&amp; err_code</code>; followed at times by something like <code>size_t sz</code> indicating how many bytes were transferred) &ndash; then the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> form of the <code>async_...()</code> method shall take <code>sync_</code>-prefixed <em>out-arg</em> counterparts to those args directly as well. Thus specifically:</p><ul>
<li>If async-I/O sig is <code>x.async_receive_blob(..., F)</code>, where <code>F()</code> is of form <code>void (const Error_code&amp; err_code, size_t sz)</code>, then:</li>
<li><code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> sig is: <code>x.async_receive_blob(..., Error_code* sync_err_code, size_t* sync_sz, F)</code>, where <code>F()</code> is of the same form as before. You shall provide <code>&amp;sync_err_code, &amp;sync_sz</code>, and your local variables shall be set to certain values upon return.<ul>
<li>You may also leave <code>sync_err_code</code> (if applicable) null. In that case standard Flow error-reporting semantics are active: if (and only if) <code>*sync_err_code</code> <em>would</em> be set to truthy (non-success) value, but <code>sync_err_code</code> is a null pointer, then a <code>flow::error::Runtime_error</code> is thrown with the would be <code>*sync_err_code</code> stored inside the exception object (and a message in its <code>.what()</code>).</li>
</ul>
</li>
</ul>
<p >So let's say you call <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> <code>x.async_receive_blob()</code>, providing it <code>&amp;sync_err_code, &amp;sz</code> args, otherwise using the same arg values as with async-I/O. (For simplicity of discussion let's assume you did not pass null pointer for the sync-err-code arg.) Then: <code>F()</code> will no longer execute from some unspecified thread at some unknown future time. Instead there are 2 possibilities.</p><ul>
<li>If <code>x.async_receive_blob()</code> was able to receive a message (more generally &ndash; complete the operation) synchronously (immediately), then:<ul>
<li>The method <em>itself</em> shall emit (via <code>sync_err_code</code> out-arg) either <em>no</em> error (falsy value) or an error (truthy value) that is specifically <em>not</em> <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297aa667487757f9d6300f6888bac40bcc24" title="A sync_io operation could not immediately complete; it will complete contingent on active async-wait ...">ipc::transport::error::Code::S_SYNC_IO_WOULD_BLOCK</a>.<ul>
<li>This is quite analogous to <code>SSL_read()</code> succeeding immediately, without <code>SSL_ERROR_WANT_*</code>.</li>
</ul>
</li>
<li>The method <em>itself</em> shall synchronously emit other <code>sync_</code> out-arg values indicating the result of the operation. In this case that is <code>sync_sz == 0</code> on error, or <code>sync_sz &gt; 0</code> indicating how many bytes long the successfully, <em>synchronously</em> received blob is.<ul>
<li>Again: This is quite analogous to <code>SSL_read()</code> succeeding immediately, without <code>SSL_ERROR_WANT_*</code>.</li>
</ul>
</li>
<li>The async completion handler, <code>F</code>, shall be utterly and completely ignored. It will <em>not</em> be saved. It will <em>not</em> be called. The operation already finished: you get to deal with it right then and there like a normal synchronous human being.</li>
</ul>
</li>
<li>Conversely, if <code>x.async_receive_blob()</code> can only complete the op after some events-of-interest (to <code>x</code>) become active (we'll discuss how this works in a moment) &ndash; then:<ul>
<li>The method <em>itself</em> shall emit (via <code>sync_err_code</code> out-arg) the specific code <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297aa667487757f9d6300f6888bac40bcc24" title="A sync_io operation could not immediately complete; it will complete contingent on active async-wait ...">ipc::transport::error::Code::S_SYNC_IO_WOULD_BLOCK</a>.<ul>
<li>This is analogous to <code>SSL_read()</code> returning <code>SSL_ERROR_WANT_*</code>.</li>
</ul>
</li>
<li>It shall save <code>F</code> internally inside <code>x</code>.</li>
<li>Later, when your loop <em>does</em> detect an event-of-interest (to <code>x</code>) is active, it shall explicitly <em>call into another <code>x</code> API method</em> &ndash; we call it <code>(*on_active_ev_func)()</code> &ndash; and <em>that</em> method may <em>synchronously</em> invoke the memorized completion handler <code>F()</code>. In the case of <code>x.async_receive_blob()</code> this <code>F()</code> call will be just as you're used-to with async-I/O pattern: <code>err_code</code> truthy on error, <code>sz == 0</code>; or <code>err_code</code> falsy on success, <code>sz &gt; 0</code> indicating size of received blob.<ul>
<li>Since <code>x.async_receive_blob()</code> has one-off completion handler semantics, at this point it'll forget <code>F</code>.</li>
<li>However, with <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern, <code>x</code> shall <em>never</em> issue an operation-aborted call to <code>F()</code> or <code>x</code> destruction or anything like that. That's an async-I/O thing.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p >The "later, when your loop" step is analogous to: your loop awaiting an event as asked by the would-block <code>SSL_read()</code>, then once active calling <code>SSL_read()</code> again; and the latter, this time, returning success. Note, however, that you do <em>not</em> re-call <code>x.async_receive_blob()</code> on the desired active event. Conceptually you're doing the same thing &ndash; you're saying, "the event you wanted is ready; if you can get what I wanted
then do it now" &ndash; but you're doing it by using a separate API.</p>
<p >That leaves the other other major piece of the API: how to in fact be informed of a desired event-of-interest and subsequently indicate that event-of-interest is indeed active. In terms of the API, this procedure is decoupled from the actual <code>x.async_receive_blob()</code> API. Moreover it is not expressed as some kind of big set-of-handles-and-events-in-which-<code>x</code>-has-interest-at-a-given-time either. Instead, conceptually, it is expressed similarly to boost.asio: <code>x</code> says to itself: I want to do <code>handle_so_and_so.async_wait(readable, F)</code>; or: I want to do <code>handle_so_and_so.async_wait(writable, F)</code>. But since <code>handle_so_and_so</code> is not a boost.asio I/O object, it has to express the same thing to the user of <code>x</code>. How? Answer: <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">sync_io::Event_wait_func</a>. Its doc header explains the details. We summarize for our chosen example of <code>x.async_receive_blob()</code>:</p><ul>
<li>Just after constructing the <code>x</code>, set up the async-wait function: <code>x.start_receive_blob_ops(E)</code>, where <code>E</code> is a function with signature a-la <code>Event_wait_func</code>.<ul>
<li>(Note that <code>receive_blob</code> fragment of the method name. This is replaced with other fragments for other operations. In some cases an object &ndash; <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">ipc::transport::Native_socket_stream</a> being a prime example &ndash; supports 2+ sets of operations. For example <code>Native_socket_stream::start_send_blob_ops()</code> is for the <em>independent</em> outgoing-direction operations that can occur <em>concurrently to</em> incoming-direction <code>start_receive_blob_ops()</code> ops.) No need to worry about that for now though; we continue with our <code>receive_blob</code> example use case.</li>
</ul>
</li>
<li><em>If</em> (and only if!) your event loop is boost.asio-based, then precede this call with one that supplies the boost.asio <code>Task_engine</code> (or strand or...) where you do your async work: <code>.replace_event_wait_handles()</code>.</li>
</ul>
<div class="fragment"><div class="line"><span class="keyword">using </span><a class="code hl_typedef" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">ipc::util::sync_io::Task_ptr</a>;</div>
<div class="line"><span class="keyword">using </span><a class="code hl_class" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">ipc::util::sync_io::Asio_waitable_native_handle</a>;</div>
<div class="line"> </div>
<div class="line">x.replace_event_wait_handles</div>
<div class="line">  ([<span class="keyword">this</span>]() -&gt; <span class="keyword">auto</span> { <span class="keywordflow">return</span> <a class="code hl_class" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">Asio_waitable_native_handle</a>(m_my_task_engine); });</div>
<div class="line">x.start_receive_blob_ops([<span class="keyword">this</span>](Asio_waitable_native_handle* hndl_of_interest,</div>
<div class="line">                                <span class="keywordtype">bool</span> ev_of_interest_snd_else_rcv,</div>
<div class="line">                                <a class="code hl_typedef" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">Task_ptr</a>&amp;&amp; on_active_ev_func)</div>
<div class="line">{</div>
<div class="line">  my_rcv_blob_sync_io_ev_wait(hndl_of_interest, ev_of_interest_snd_else_rcv, std::move(on_active_ev_func));</div>
<div class="line">});</div>
<div class="ttc" id="aclassipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle_html"><div class="ttname"><a href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">ipc::util::sync_io::Asio_waitable_native_handle</a></div><div class="ttdoc">Useful if using the sync_io pattern within a user event loop built on boost.asio (optionally with flo...</div><div class="ttdef"><b>Definition:</b> <a href="asio__waitable__native__hndl_8hpp_source.html#l00080">asio_waitable_native_hndl.hpp:81</a></div></div>
<div class="ttc" id="anamespaceipc_1_1util_1_1sync__io_html_ac6973c71fc70c6d867b0f2255c642532"><div class="ttname"><a href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">ipc::util::sync_io::Task_ptr</a></div><div class="ttdeci">boost::shared_ptr&lt; Task &gt; Task_ptr</div><div class="ttdoc">Short-hand for ref-counted pointer to a Function&lt;&gt; that takes no arguments and returns nothing; in pa...</div><div class="ttdef"><b>Definition:</b> <a href="sync__io__fwd_8hpp_source.html#l00585">sync_io_fwd.hpp:585</a></div></div>
</div><!-- fragment --><p >We are now ready for the last sub-piece: named <code>my_rcv_blob_sync_io_ev_wait()</code> in that snippet. This key piece responds to the instruction: async-wait for the specified event for me please, and let me know when that event is active by calling <code>(*on_active_ev_func)()</code> at that time. The details of how exactly to do this can be found in the <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">sync_io::Event_wait_func</a> doc header &ndash; including tips on integrating with <code>poll()</code> and <code>epoll_*()</code>. Here we will assume you have a boost.asio loop, continuing from the above snippet. The simplest possible continuation:</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> my_rcv_blob_sync_io_ev_wait(<a class="code hl_class" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">Asio_waitable_native_handle</a>* hndl_of_interest,</div>
<div class="line">                                 <span class="keywordtype">bool</span> ev_of_interest_snd_else_rcv,</div>
<div class="line">                                 <a class="code hl_typedef" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">Task_ptr</a>&amp;&amp; on_active_ev_func)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// sync_io wants us to async-wait.  Oblige.</span></div>
<div class="line">  hndl_of_interest-&gt;async_wait(ev_of_interest_snd_else_rcv</div>
<div class="line">                                 ? Asio_waitable_native_handle::Base::wait_write</div>
<div class="line">                                 : Asio_waitable_native_handle::Base::wait_read,</div>
<div class="line">                               [<span class="keyword">this</span>, on_active_ev_func = std::move(on_active_ev_func)]</div>
<div class="line">                                 (<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code)</div>
<div class="line">  {</div>
<div class="line">    <span class="keywordflow">if</span> (err_code == boost::asio::error::operation_aborted) { <span class="keywordflow">return</span>; } <span class="comment">// Shutting down?  Get out.</span></div>
<div class="line"> </div>
<div class="line">    <span class="comment">// Event is active.  sync_io wants us to inform it of this.  Oblige.</span></div>
<div class="line">    (*on_active_ev_func)();</div>
<div class="line">    <span class="comment">// ^-- THAT POTENTIALLY INVOKED COMPLETION HANDLER F() WE PASS IN TO x.async_receive_blob(F)!!!</span></div>
<div class="line">  });</div>
<div class="line">}</div>
</div><!-- fragment --><p >That's it. Note well: <code>(*on_active_ev_func)()</code> is (a) informing <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing <code>x</code> of the event it (<code>x</code>) wanted; and (b) possibly getting the result <em>you</em> wanted in the original <code>async_receive_*()</code> call. Thus it is the equivalent of the 2nd <code>SSL_read()</code> call, after satisying the <code>SSL_ERROR_WANT_READ</code> or <code>SSL_ERROR_WANT_WRITE</code> result. The only difference, really, is the mechanic of getting the result is through a <em>synchronous</em> call to your completion handler.</p>
<p >There is, however, an extremely important subtlety to consider additionally. The key point:</p><ul>
<li><code>(*on_active_ev_func)()</code> should be thought of as an API &ndash; a method! &ndash; of <code>x</code>, the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing Flow-IPC object...</li>
<li>...right alongside (in our use case here) <code>.async_receive_blob()</code>.</li>
</ul>
<p >That means it is <em>not</em> thread-safe to call <code>(*on_active_ev_func)()</code> concurrently with <code>x.async_receive_blob()</code>. What does this mean in practice? Answer:</p><ul>
<li>If you execute all these things in a single-threaded event loop &ndash; nothing. You need not worry about synchronization.</li>
<li>If you perform some of your work on <code>x</code> (perhaps the <code>.async_*()</code> calls) in one thread but the async-wait handling &ndash; and the potentially resulting <em>synchronous</em> invocation of your own completion handlers &ndash; in another...<ul>
<li>...then you, at a minimum, need a mutex-lock (or use of a strand, or ...) around the call sites into <code>x.method(...)</code>, for all related <code>method</code>s of <code>x</code>...</li>
<li>...*including* the call to <code>(*on_active_ev_func)()</code>.</li>
</ul>
</li>
</ul>
<p >Chances are, though, that if you're operating in multiple threads, then anyway you'll need to protect <em>your own</em> data structures against concurrent writing. Remember: <code>(*on_active_ev_func)()</code> may well invoke <em>your own completion handler</em> from the original <code>x.async_receive_blob(..., F)</code> call. That code (<em>your</em> code) is more than likely to react to the received payload in some way, and that might be touching data structures accessed from 2+ threads. It would therefore make sense that the relevant mutex be already locked. In this example we presuppose your application might invoke async-receives from a thread U while placing handlers onto a thread W:</p>
<div class="fragment"><div class="line"><span class="keyword">using </span>flow::util::Lock_guard;</div>
<div class="line"> </div>
<div class="line">...</div>
<div class="line">  <span class="comment">// In your thread U:</span></div>
<div class="line"> </div>
<div class="line">  Lock_guard&lt;<span class="keyword">decltype</span>(m_my_rcv_mutex)&gt; lock(m_my_rcv_mutex); <span class="comment">// &lt;-- ATTN!  Protects x receive ops at least.</span></div>
<div class="line">  ...</div>
<div class="line">  <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">ipc::Error_code</a> sync_err_code;</div>
<div class="line">  <span class="keywordtype">size_t</span> sync_sz;</div>
<div class="line">  x.async_receive_blob(m_target_msg,</div>
<div class="line">                       &amp;sync_err_code, &amp;sync_sz,</div>
<div class="line">                       [<span class="keyword">this</span>](<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">ipc::Error_code</a>&amp; err_code, <span class="keywordtype">size_t</span> sz) { on_msg_in(err_code, sz); });</div>
<div class="line">  <span class="keywordflow">if</span> (sync_err_code != <a class="code hl_enumvalue" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297aa667487757f9d6300f6888bac40bcc24">ipc::transport::error::Code::S_SYNC_IO_WOULD_BLOCK</a>)</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// ...Handle contents of m_target_msg, or sync_err_code indicating error ion -- perhaps ~like on_msg_in()!</span></div>
<div class="line">    <span class="comment">// Note m_my_rcv_mutex is locked... as it would be in on_msg_in() (which won&#39;t run in this case)!</span></div>
<div class="line">  }</div>
<div class="line">  <span class="comment">// else { on_msg_in() will run later.  x.receive_...() probably invoked my_rcv_blob_sync_io_ev_wait(). }</span></div>
<div class="line">...</div>
<div class="line"> </div>
<div class="line">void my_rcv_blob_sync_io_ev_wait(Asio_waitable_native_handle* hndl_of_interest,</div>
<div class="line">                                 <span class="keywordtype">bool</span> ev_of_interest_snd_else_rcv,</div>
<div class="line">                                 <a class="code hl_typedef" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">Task_ptr</a>&amp;&amp; on_active_ev_func)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// In your thread U:</span></div>
<div class="line"> </div>
<div class="line">  <span class="comment">// sync_io wants us to async-wait.  Oblige.  (Do not lock m_my_rcv_mutex!)</span></div>
<div class="line">  hndl_of_interest-&gt;async_wait(ev_of_interest_snd_else_rcv</div>
<div class="line">                                 ? Asio_waitable_native_handle::Base::wait_write</div>
<div class="line">                                 : Asio_waitable_native_handle::Base::wait_read,</div>
<div class="line">                               [<span class="keyword">this</span>, on_active_ev_func = std::move(on_active_ev_func)]</div>
<div class="line">                                 (<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code)</div>
<div class="line">  {</div>
<div class="line">    <span class="keywordflow">if</span> (err_code == boost::asio::error::operation_aborted) { <span class="keywordflow">return</span>; } <span class="comment">// Shutting down?  Get out.</span></div>
<div class="line"> </div>
<div class="line">    <span class="comment">// In your thread W:</span></div>
<div class="line"> </div>
<div class="line">    <span class="comment">// Event is active.  sync_io wants to inform it of this.  Oblige.</span></div>
<div class="line"> </div>
<div class="line">    flow::util::Lock_guard&lt;<span class="keyword">decltype</span>(m_my_rcv_mutex)&gt; lock(m_my_rcv_mutex); <span class="comment">// &lt;-- ATTN!</span></div>
<div class="line"> </div>
<div class="line">    (*on_active_ev_func)();</div>
<div class="line">    <span class="comment">// ^-- THAT POTENTIALLY INVOKED on_msg_in()!!!</span></div>
<div class="line">  });</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> on_msg_in(<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code, <span class="keywordtype">size_t</span> sz)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// In your thread W:</span></div>
<div class="line">  <span class="comment">// m_my_rcv_mutex is locked!</span></div>
<div class="line"> </div>
<div class="line">  ... <span class="comment">// Handle contents of m_target_msg, or err_code indicating error.</span></div>
<div class="line">}</div>
<div class="ttc" id="anamespaceipc_1_1transport_1_1error_html_adfef15ef4e76cc55d652fbd9c2797297aa667487757f9d6300f6888bac40bcc24"><div class="ttname"><a href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297aa667487757f9d6300f6888bac40bcc24">ipc::transport::error::Code::S_SYNC_IO_WOULD_BLOCK</a></div><div class="ttdeci">@ S_SYNC_IO_WOULD_BLOCK</div><div class="ttdoc">A sync_io operation could not immediately complete; it will complete contingent on active async-wait ...</div></div>
</div><!-- fragment --><p >Just remember: <em>You</em> choose when <code>x</code> does anything that might touch your data, or itself. This happens in exactly three possible places and always synchronously:</p><ul>
<li>The <code>x.async_receive_blob()</code> initiating call itself (and ones like it, all having async-I/O almost-identical-sig counterparts in <code>X::</code> for any given <code>sync_io::X::</code>).<ul>
<li>OpenSSL analogy: initial <code>SSL_read()</code>.</li>
</ul>
</li>
<li>Your code reacting to non-would-block return from <code>x.async_receive_blob()</code>, right after it (and ones like it).<ul>
<li>OpenSSL analogy: reacting to initial <code>SSL_read()</code> succeeding right away.</li>
</ul>
</li>
<li><code>(*on_active_ev_func)()</code>.<ul>
<li>OpenSSL analogy: subsequent <code>SSL_read()</code>, once you've detected its <code>SSL_ERROR_WANT_*</code> has been satisfied.</li>
</ul>
</li>
</ul>
<h3>Is there always a completion handler?</h3>
<p >Answer: No. An async op might not have a completion handler, but it is still an async op and may need to ask you to async-wait for some handle to be readable and/or writable to work properly. The most prominent case of this is sending items as exemplified by <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html#a2e1474a87ee8f5ec18bf6cc8d6cfe7b2" title="Implements Blob_sender API per contract.">ipc::transport::sync_io::Native_socket_stream::send_blob()</a>. How to handle it? Well, it's the same as any <code>async_*()</code> op (which shall always take a completion handler) &ndash; but simpler. Simply put: Such an op shall be initiated by a method that takes no completion handler arg, so you simply don't provide one. (By convention it will also lack an <code>async_</code> prefix in the method name.) Beyond that, everything is the same:</p><ul>
<li>It may (or may not) initiate an async-wait by calling the <code>Event_wait_func</code> you supplied via <code>start_*ops()</code>.</li>
<li>Your <code>Event_wait_func</code> should indeed &ndash; on successful async-wait &ndash; invoke <code>(*on_active_ev_func)()</code>. Internally that may continue, or complete, whatever async processing <code>x</code> needs to do.<ul>
<li>The difference: it won't invoke some completion handler of yours... as you didn't (and couldn't) provide one.</li>
</ul>
</li>
</ul>
<h3>Multiple op-types in a given <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing object</h3>
<p >Consider, first, <a class="el" href="classipc_1_1session_1_1sync__io_1_1Session__server__adapter.html" title="sync_io-pattern counterpart to async-I/O-pattern session::Session_server types and all their SHM-awar...">ipc::session::sync_io::Session_server_adapter</a>. It has only one operation, really: <a class="el" href="classipc_1_1session_1_1sync__io_1_1Session__server__adapter.html#a2abb42ee66fa0006c675975bf4bed380" title="Acts identically to 1-arg overload of Session_server::async_accept(), except that the completion hand...">session::sync_io::Session_server_adapter::async_accept()</a>. To set it up, you'll do (as explained above by another example use case): <code>x.start_ops()</code>, possibly preceded by <code>x.replace_event_wait_handles()</code> (but that guy is beside the point).</p>
<p >Easy enough. The <code>x</code> can't do any other "type of thing." Same is true of, say, <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Blob__stream__mq__sender.html" title="Implements sync_io::Blob_sender concept by using an adopted Persistent_mq_handle MQ handle to an MQ (...">ipc::transport::sync_io::Blob_stream_mq_sender</a>: it can only <code>x.send_blob()</code> (and <code>x.auto_ping()</code>, <code>x.end_sending()</code>, <code>x.async_end_sending()</code> &ndash; all of which deal with sending messages <em>out</em>); and needs only <code>x.start_send_blob_ops()</code> for setup.</p>
<p >What if an object can do multiple things though? <code>Native_socket_stream</code> (operating as a <code>Blob_sender</code> and <code>Blob_receiver</code>) can do at least 2: it can</p><ul>
<li>send (<code>.send_blob()</code>, <code>.end_sending()</code>, <code>.async_end_sending()</code>, <code>.auto_ping()</code>),</li>
<li>and receive (<code>.async_receive_blob()</code>, <code>.idle_timer_run()</code>).</li>
</ul>
<p >These are 2 distinct <em>op-types</em>, and each one has its own independent API started via <code>.start_send_blob_ops()</code> and <code>.start_receive_blob_ops()</code> respectively. (If it were networked &ndash; this might be in the works &ndash; it would probably gain a 3rd op-type via <code>.start_connect_ops()</code>.)</p>
<p >Not that interesting in and of itself; but what about concurrency? Answer:</p>
<p >Things only get interesting once 2+ op-types (in practice, as of this writing, it's 2 at most in all known use cases) can occur concurrently. Namely that's sending (started via <code>.start_send_blob_ops()</code> in this case) and receiving (<code>.start_receive_blob_ops()</code>). How does it work? Answer: Formally speaking, it's described in the appropriate class's doc header; in this case <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html" title="Implements both sync_io::Native_handle_sender and sync_io::Native_handle_receiver concepts by using a...">ipc::transport::sync_io::Native_socket_stream</a>. Informally the intuition behind it is as follows:</p><ul>
<li>In a full-duplex object (like this one), you can indeed send and receive at the same time. That is, e.g., you can interleave an async-receive-blob op and its eventual completion with invoking something send-related and its eventual completion (if applicable).</li>
<li>Moreover you can use the API of op-type "receive" <em>actually concurrently</em> with the API of op-type "send." It <em>is</em> thread-safe, even though you're ostensily mutating the same object <code>x</code>. This is analogous to being able to concurrently <code>read(fd, ...)</code> and <code>write(fd, ...)</code> on the same OS handle <code>fd</code> for many socket types including TCP and Unix-domain-socket. This may, all in all, lead to significant perf savings in your application, if you have multiple threads available to handle sending and receiving. If you <em>do</em> need a mutex, you can have 1 mutex for send ops and 1 mutex for receive ops (assuming of course your algorithm doesn't involve the 2 directions' algorithms concurrently mutating the same outside-<code>x</code> data).</li>
</ul>
<p >Do keep in mind: This applies to <code>sync_io::X</code> only &ndash; not its async-I/O counterpart <code>X</code>. E.g., you cannot do <code>x.async_receive_blob()</code> and <code>x.send_blob()</code> concurrently, in the latter case, but you can too do so in the former. With plain <code>X</code> you'd need to mutex-protect (or use strands or ...) <code>x</code>. However you can of course still have 2+ async operations outstanding simultaneously (e.g., initiating a send while an <code>.async_receive_*(..., F)</code> has not yet finished as signified by <code>F()</code>): you just cannot literally call mutating parts of <code>x</code> API concurrently.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">ipc::util::sync_io::Event_wait_func</a> &ndash; details about hooking up your event loop to a <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing Flow-IPC object. </dd>
<dd>
<a class="el" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html" title="Useful if using the sync_io pattern within a user event loop built on boost.asio (optionally with flo...">ipc::util::sync_io::Asio_waitable_native_handle</a> &ndash; take a look particularly if your event loop is built on boost.asio. </dd>
<dd>
<a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">ipc::transport::Native_socket_stream</a> internal source code: This exemplifies a fairly advanced "eat-our-own-dog-food" usage of a <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing API (<a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html" title="Implements both sync_io::Native_handle_sender and sync_io::Native_handle_receiver concepts by using a...">ipc::transport::sync_io::Native_socket_stream</a> in this case) in a multi-threaded setting (user's thread U and internal worker thread W in this case). In this case the event loop is a boost.asio one.</dd></dl>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000022">Todo:</a></b></dt><dd>Write an example of <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern use with an old-school reactor-pattern event loop, using <code>poll()</code> and/or <code>epoll_*()</code>.</dd></dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html" title="An object of this type, used internally to implement sync_io-pattern objects that require timer event...">ipc::util::sync_io::Timer_event_emitter</a> &ndash; how to hook up a boost.asio <code>Timer</code> inside a <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-implementing Flow-IPC object. </dd></dl>
</div><h2 class="groupheader">Typedef Documentation</h2>
<a id="aa0b9a3cc6bdc7dedbef4f9e06851aa24" name="aa0b9a3cc6bdc7dedbef4f9e06851aa24"></a>
<h2 class="memtitle"><span class="permalink"><a href="#aa0b9a3cc6bdc7dedbef4f9e06851aa24">&#9670;&nbsp;</a></span>Event_wait_func</h2>

<div class="memitem">
<div class="memproto">
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24">ipc::util::sync_io::Event_wait_func</a> = typedef <a class="el" href="namespaceipc.html#aa455c7f045059736578ca275fc1a851f">Function</a>&lt;void (<a class="el" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html">Asio_waitable_native_handle</a>* hndl_of_interest, bool ev_of_interest_snd_else_rcv, <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">Task_ptr</a>&amp;&amp; on_active_ev_func)&gt;</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>In <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern, concrete type storing user-supplied function invoked by pattern-implementing <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> and <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> object to indicate interest in an I/O status event (writable, readable) for a particular <a class="el" href="structipc_1_1util_1_1Native__handle.html" title="A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.">Native_handle</a>. </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">ipc::util::sync_io</a> doc header first. It explains the pattern in detail including example code for setting up an <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">Event_wait_func</a></code>.</dd></dl>
<h2>Use in <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern </h2>
<p >Suppose <code>T</code> is an <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> or <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> object type, always in a <code>"sync_io"</code> sub-namespace, that operates according to the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern. (For example, <code>T</code> might be <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html" title="Implements both sync_io::Native_handle_sender and sync_io::Native_handle_receiver concepts by using a...">transport::sync_io::Native_socket_stream</a>.) Then <code>T::start_*ops(Event_wait_func&amp;&amp;)</code>, and/or a compatible template, must be invoked to begin unidirectional work of type X (e.g., <code>start_*ops()</code> might be <code>start_send_blob_ops()</code> or <code>start_receive_native_handle_ops()</code>) on a given <code>T</code>; the <code>T</code> memorizes the function until its destruction.</p>
<p >From that point on, the <code>T</code> might at times be unable to complete an operation (for example <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html#a2e1474a87ee8f5ec18bf6cc8d6cfe7b2" title="Implements Blob_sender API per contract.">transport::sync_io::Native_socket_stream::send_blob()</a>) synchronously due to a would-block condition on some internal <a class="el" href="structipc_1_1util_1_1Native__handle.html" title="A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.">Native_handle</a> (for example, internally, the Unix domain stream socket in this case encountering would-block on a <code>"::writemsg()"</code> attempt). It shall then &ndash; synchronously, inside <code>Native_socket_stream::send_blob()</code> &ndash; invoke the saved <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">Event_wait_func</a> and pass to it the following arguments:</p><ul>
<li><code>hndl_of_interest</code>: The native handle on which the user's own event loop must wait for an I/O event. In-depth tips on how to do so are below; but for now:<ul>
<li>If your event loop is built on boost.asio, you may use <code>hndl_of_interest-&gt;async_wait()</code> directly.</li>
<li>Otherwise (if you're using <code>[e]poll*()</code> perhaps), obtain the raw handle as follows: <code>hndl_of_interest-&gt;native_handle().m_native_handle</code>. It can be input to <code>poll()</code>, <code>epoll_ctl()</code>, etc.</li>
</ul>
</li>
<li><code>ev_of_interest_snd_else_rcv</code>: Which event it must await: <code>true</code> means "writable"; <code>false</code> means "readable."<ul>
<li>What if the user's wait (such as <code>epoll_wait()</code>) encounters an error-occurred event instead (<code>EPOLLERR</code>)? Answer: They must in fact report this as-if the requested event (whether writable or readable) is active.</li>
</ul>
</li>
<li><code>on_active_ev_func</code>: If (and, to avoid pointless perf loss, only if) the above-specified event is active, the user must invoke <code>(*on_active_ev_func)()</code> (without args and expecting no return value).<ul>
<li>In terms of thread safety, and generally, one should consider this function a non-<code>const</code> member of <code>T</code>'s sub-API. (The sub-API in question is the set of methods that correspond to unidirectional-operation of type X, where <code>T::start_*ops()</code> was invoked to kick things off. For example, in <code>Native_socket_stream</code> as used as a Blob_sender, that's its <code>send_blob()</code> and <code>*end_sending()</code> methods.) That is, <code>(*on_active_ev_func)()</code> may not be called concurrently to any <code>T</code> sub-API method (<code>Native_socket_stream::send_blob()</code>, <code>*end_sending()</code> in the recent example) or other <code>(*on_active_ev_func)()</code>. <code>(*on_active_ev_func)()</code> may well, itself, synchronously invoke <code>Event_wait_func</code> to indicate interest in a new event.</li>
</ul>
</li>
</ul>
<p >Naturally the key question arises: what, specifically, should a particular <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">Event_wait_func</a> (as passed-into a <code>T::start_*ops()</code>) <em>do</em>? Indeed, this requires great care on the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern user's part.</p>
<p >Formally speaking the contract is as follows. Let <code>F</code> be the particular <code>Event_wait_func</code>.</p><ol type="1">
<li>Upon <code>F()</code> being called, it shall register &ndash; through a technique of the user's choice (a couple are explained below for your convenience) &ndash; the specified event as one of interest. The sooner this registration occurs, the more responsively <code>T</code> will behave.</li>
<li>It shall arrange, via that same technique, to do the following upon detecting the event (or <code>hndl_of_interest</code> becoming hosed, i.e., the error event). The sooner it does so, the more responsively <code>T</code> will behave.<ol type="a">
<li><em>Deregister</em> the specified event. Each <code>Event_wait_func</code> invocation indicates a <b>one-off</b> wait.</li>
<li>Call <code>(*on_active_ev_func)()</code>. (It is best, for a little perf bump, for the user to save <code>std::move(on_active_ev_func))</code> as opposed to a smart-pointer copy.)</li>
</ol>
</li>
</ol>
<dl class="section warning"><dt>Warning</dt><dd>Do not forget to deregister the event before <code>(*on_active_ev_func)()</code>. Failure to do so can easily result in processor pegging at best; or undefined behavior/assertion tripping. Worse still, if it's mere processor pegging, you might not notice it happening. E.g., if <code>Native_socket_stream::send*()</code> encounters would-block internally, it will register interest in writability of an internal handle; suppose when you report writability it is able to push-through any queued internal payload. Now it no longer needs writability; if informed of writability anyway, it will at best do nothing &ndash; leading to an infinite loop of user reporting writability and <code>Native_socket_stream</code> ignoring it. Or, if that is how <code>Native_socket_stream</code> is written, it will detect that a write event is being reported despite it not asking for this and log WARNING or even FATAL/abort program. With <code>epoll_*()</code>, <code>EPOLLONESHOT</code> and/or <code>EPOLLET</code> may be of aid, but be very careful.</dd>
<dd>
With this mechanism we are exposing native handles/FDs on which work is potentially performed by Flow-IPC internals. You may perform operations only as described here, namely read-only "watching" of events; do not transmit anything or close such handles under any circumstances. In addition such a native handle is guaranteed to be valid until the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern object exists, but once the destructor begins you must never touch it again. Corollary: See warning below in <code>epoll</code>-focused section below.</dd></dl>
<h3>Integrating with reactor-pattern <code>poll()</code> and similar</h3>
<p >Suppose your application is using POSIX <code>poll()</code>. Typically a data structure will be maintained mirroring the <code>fds[].events</code> (events of interest) sub-argument to <code>poll()</code>; for example an <code>unordered_map&lt;&gt;</code> from FD (<a class="el" href="structipc_1_1util_1_1Native__handle.html#ab2f496740139c5752a25a30cf3325d86" title="The native handle (possibly equal to S_NULL_HANDLE), the exact payload of this Native_handle.">Native_handle::m_native_handle</a>) to an <code>enum { S_NONE, S_RD, S_WR, S_RD_WR }</code>; or simply the <code>fds[]</code> array itself. (In the latter case lookup by FD may not be constant-time. However <code>fds[].events</code> does not need to be built from a mirroring structure ahead of each <code>poll()</code>.)</p>
<p >When <code>Event_wait_func F(hndl, snd_else_rcv, on_ev_func)</code> is invoked, you will register the event:</p><ol type="1">
<li>If necessary, insert <code>raw_hndl = hndl-&gt;native_handle().m_native_handle</code> into the data structure, with no events of interest (which will change in the next step). If not necessary (already inserted, hence with a (different) event of interest already), continue to next step.</li>
<li>Depending on <code>snd_else_rcv</code>, change the events-of-interest <code>enum</code> NONE-&gt;RD, NONE-&gt;WR, WR-&gt;RD_WR, or RD-&gt;RD_WR. (If operating on an <code>fd[].events</code> directly, that's: <code>fd.events = fd.events | POLLIN</code> or <code>fd.events = fd.events | POLLOUT</code>.)</li>
<li>In some data structure keyed on, conceptually, the pair <code>(raw_hndl, bool snd_else_rcv)</code>, record <code>std::move(on_ev_func)</code>. Call it, say, <code>ipc_events_map</code>.</li>
</ol>
<p >At some point in your reactor-pattern event loop, you are ready to call <code>poll()</code>. Construct <code>fds[].events</code> array if needed, or just use the long-term-maintained one, depending on how you've set this up. Call <code>poll()</code>. For each <em>individual</em> active event in an <code>fds[].revents</code>:</p><ol type="1">
<li>Construct the pair <code>(raw_hndl, snd_else_rcv)</code>.</li>
<li>If it's not in <code>ipc_events_map</code>, no IPC-relevant event fired; it must be something relevant to other parts of your application (such as network traffic). Exit algorithm for now (until next <code>poll()</code>); the IPC-registered event is still being waited-on.</li>
<li>If it <em>is</em> in <code>ipc_events_map</code>:<ol type="a">
<li>Remove it from there.</li>
<li>Deregister the event w/r/t next <code>poll()</code>:<ol type="i">
<li>Depending on <code>snd_else_rcv</code>: Change the events-of-interest <code>enum</code> RD-&gt;NONE, WR-&gt;NONE, RD_WR-&gt;WR, or RD_WR-&gt;RD. (If operating on an <code>fd[].events</code> directly, that's <code>fd.events = fd.events &amp; ~POLLIN)</code> or <code>fd.events = fd.events &amp; ~POLLOUT</code>.)</li>
<li>If the events-of-interest for the FD have become NONE (or <code>fd.events == 0</code> if tracking it directly), delete the handle's entry from the <code>events</code>-mirroring structure (or <code>events</code> itself if tracking it directly).</li>
</ol>
</li>
<li>Invoke the saved <code>(*on_ev_func)()</code>.</li>
</ol>
</li>
</ol>
<dl class="section note"><dt>Note</dt><dd>While each <code>F()</code> invocation indicates one-off event interest, the handler <code>(*on_ev_func)()</code> will sometimes, or possibly frequently, re-indicate interest in the same event within its own handler. If done very carefully, it <em>might</em> be possible to detect this situation by deferring the editing of <code>events</code> or the mirroring structure until <code>(*on_ev_func)()</code> finishes; possibly this would net to making no change to the events-of-interest structure. This could save some processor cycles. I (ygoldfel) would recommend only getting into that if compelling perf savings evidence appears.</dd>
<dd>
You might notice <code>hndl</code> is a pointer to <a class="el" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html" title="Useful if using the sync_io pattern within a user event loop built on boost.asio (optionally with flo...">Asio_waitable_native_handle</a>, but you simply get <code>raw_hndl</code> out of it and forget about the rest of <code>*hndl</code>. Why not just provide <code>raw_hndl</code> to you? Answer: It is useful when <em>not</em> integrating with a reactor-pattern event loop a-la <code>poll()</code> or similar but rather when integrating with a boost.asio event loop. See "Integrating with boost.asio" below.</dd></dl>
<h3>What about <code>epoll_*()</code>?</h3>
<p >In Linux <code>epoll_*()</code> is considered superior (its <code>man</code> page at least says that, when used in non-<code>EPOLLET</code> mode, it is a "faster" <code>poll()</code>). We leave the exercise of how to apply the above suggestions (for <code>poll()</code>) to <code>epoll_*()</code> to the reader. Briefly: Essentially <code>epoll_ctl()</code> lets the kernel track a long-running <code>fds[].events</code> sub-array, with add/remove/modify operations specified by the user as syscalls. However, it's not possible to simply say "I am interested in FD X, event writable"; the events-of-interest per FD are still specified as an ORing of <code>EPOLLIN</code> and/or <code>EPOLLOUT</code> in one per-FD entry, whereas <code>Event_wait_func</code> is finer-grained than that. It is not possible to iterate through the kernel-stored events-of-interest set or obtain the existing <code>events</code> bit-mask so as to then <code>|=</code> or <code>&amp;=</code> it. Therefore a mirroring data structure (such as the aforementioned <code>unordered_map&lt;&gt;</code> from FD to rd/wr/rd-wr) may be necessary in practice. In my (ygoldfel) experience using such a mirroring thing is typical in any case.</p>
<dl class="section warning"><dt>Warning</dt><dd>When a <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code>-pattern-API object (e.g., <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html" title="Implements both sync_io::Native_handle_sender and sync_io::Native_handle_receiver concepts by using a...">transport::sync_io::Native_socket_stream</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">transport::struc::sync_io::Channel</a> or <a class="el" href="classipc_1_1session_1_1sync__io_1_1Server__session__adapter.html" title="sync_io-pattern counterpart to async-I/O-pattern session::Server_session types and all their SHM-awar...">session::sync_io::Server_session_adapter</a>) is about to be destroyed (by you), it is very possible you have 1+ outstanding async-waits on 1+ native handles (FDs). You <em>must</em> deregister any earlier <code>epoll_ctl(...ADD)</code>s via <code>epoll_ctl(...DEL)</code>, and you must do so <em>before</em> destroying the Flow-IPC object. Failure to do so can lead to unexpected chaos (such as <a href="https://idea.popcount.org/2017-03-20-epoll-is-fundamentally-broken-22/">explained here</a>). Conversely doing so but after Flow-IPC object destructor has begun executing breaks the earlier-mentioned rule wherein a handle must not be touched at that point (and is likely invalid or refers to something else by then).</dd></dl>
<p>One tip: <code>EPOLLONESHOT</code> may be quite useful: It means you can limit your code to just doing <code>epoll_ctl(...ADD)</code> without requiring the counterpart <code>epoll_ctl(...DEL)</code> once the event does fire. (<code>EPOLLET</code> may be usable to decrease the number of epoll-ctl calls needed further, but as of this writing we haven't investigated this sufficiently to make a statement.)</p>
<p >However <code>EPOLLONESHOT</code> pertains to the entire descriptor, not one specific waited-on event (read or write). Therefore this optimization is helpful only if <code>.events</code> is being set to <code>EPOLLIN</code> or <code>EPOLLOUT</code> &ndash; not <code>EPOLLIN | EPOLLOUT</code>. Be careful. That said, it should be possible to use <code>dup()</code> to clone the descriptor in question; then use the original for (e.g.) <code>EPOLLIN</code> exclusively and the clone for <code>EPOLLOUT</code> exclusively resulting in a clean solution.</p>
<h3>Integrating with boost.asio</h3>
<p >Suppose your application is using boost.asio (possibly with flow.async to manage threads), with a <code>flow::util::Task_engine::run()</code> embodying the event loop, in proactor pattern fashion. (We would recommend just that, preferring it to an old-school reactor-pattern via <code>[e]poll*()</code> directly.) <em>Your</em> loop is asynchronously expressed, but you can still use the <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern to graft Flow-IPC operations into it, so that they are invoked synchronously, when you want, in the exact thread you want. In fact, doing so is <em>significantly</em> simpler than integrating with a reactor-style <code>[e]poll*()</code>. That is because, conceptually, each <code>Event_wait_func</code> invocation is essentially expressing the following boost.asio operation:</p>
<div class="fragment"><div class="line">some_low_level_transport.async_wait(wait_write, <span class="comment">// (or `wait_read`.)</span></div>
<div class="line">                                    [...](<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// Can do I/O, or error?  Do I/O, or handle error.</span></div>
<div class="line">  <span class="comment">// ...If no error then possibly even at some point continue the async-op chain...</span></div>
<div class="line">  same_or_other_low_level_transport.async_wait(wait_write, <span class="comment">// (or `wait_read`.)</span></div>
<div class="line">                                               ...);</div>
<div class="line">}</div>
</div><!-- fragment --><p >Because of that you have to code essentially none of the stuff above (pertaining to a reactor-style <code>[e]poll*()</code> loop): no manual registering/deregistering, wondering how to handle error-event, etc. etc.</p>
<p >So what to do, specifically? It is quite straightforward. Suppose you're got <code>Task_engine E</code> doing <code>E.run()</code> as your event loop. (Any <code>flow::async::*_loop</code> does that too, just internally once you do <code>loop.start()</code>.) E.g., if you've got TCP sockets attached to <code>E</code>, you might be doing <code>m_tcp_sock.async_read_some(..., [](const Error_code&amp; err_code) { ... };</code> and so on.</p>
<p >When <code>Event_wait_func F(hndl, snd_else_rcv, on_ev_func)</code> is invoked, you will simply do:</p>
<div class="fragment"><div class="line">hndl-&gt;async_wait(snd_else_rcv ? Asio_waitable_native_handle::Base::wait_write</div>
<div class="line">                              : Asio_waitable_native_handle::Base::wait_read,</div>
<div class="line">                 [on_ev_func = std::move(on_ev_func)](<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code)</div>
<div class="line">{</div>
<div class="line">  <span class="keywordflow">if</span> (err_code != boost::asio::error::operation_aborted)</div>
<div class="line">  {</div>
<div class="line">    (*on_ev_func)(); <span class="comment">// Note: err_code is disregarded.  Whether it&#39;s readable/writable or hosed, must invoke.</span></div>
<div class="line">  }</div>
<div class="line">  <span class="comment">// else { Stuff is shutting down; do absolutely nothing!  SOP on operation_aborted generally. }</span></div>
<div class="line">}</div>
</div><!-- fragment --><p >Basically, Flow-IPC wants to do an <code>async_wait()</code>... so you do it for Flow-IPC, being the master of your (boost.asio) domain (so to speak).</p>
<p ><code>hndl</code> is an <code>Asio_waitable_native_handle*</code>. <a class="el" href="classipc_1_1util_1_1sync__io_1_1Asio__waitable__native__handle.html" title="Useful if using the sync_io pattern within a user event loop built on boost.asio (optionally with flo...">Asio_waitable_native_handle</a> is a razor-thin wrapper around a boost.asio <code>posix::descriptor</code> which itself is a thin wrapper around a native handle (FD). It has boost.asio-supplied <code>.async_wait()</code>. However, and this is a key point:</p>
<p >To make it work, before invoking <code>T::start_*ops()</code>, you must supply your execution context/executor &ndash; usually a boost.asio <code>Task_engine</code> (a/k/a <code>boost::asio::io_context</code>) or strand (<code>boost::asio::io_context::strand</code>) &ndash; w/r/t which you plan to <code>.async_wait()</code> down the line. This is done via <code>T::replace_event_wait_handles()</code>, an otherwise optional call. If using flow.async, this might be (e.g.):</p>
<div class="fragment"><div class="line">flow::async::Single_thread_task_loop m_your_single_threaded_event_loop;</div>
<div class="line"><a class="code hl_class" href="classipc_1_1transport_1_1Native__socket__stream.html">ipc::transport::Native_socket_stream</a> m_sock_stream;</div>
<div class="line"><span class="comment">// ...</span></div>
<div class="line">m_sock_stream.replace_event_wait_handles([<span class="keyword">this</span>]() -&gt; <span class="keyword">auto</span></div>
<div class="line">{</div>
<div class="line">  <span class="keywordflow">return</span> ipc::util::async_io::Asio_waitable_native_handle</div>
<div class="line">           (*(m_your_single_threaded_event_loop.task_engine()));</div>
<div class="line">});</div>
<div class="line">m_sock_stream.start_send_blob_ops(F); <span class="comment">// F is your Event_wait_func.</span></div>
<div class="ttc" id="aclassipc_1_1transport_1_1Native__socket__stream_html"><div class="ttname"><a href="classipc_1_1transport_1_1Native__socket__stream.html">ipc::transport::Native_socket_stream</a></div><div class="ttdoc">Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...</div><div class="ttdef"><b>Definition:</b> <a href="native__socket__stream_8hpp_source.html#l00270">native_socket_stream.hpp:271</a></div></div>
</div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>As explained in "Integrating with reactor-pattern..." above, <code>hndl</code> is a boost.asio I/O object, as opposed to just a <a class="el" href="structipc_1_1util_1_1Native__handle.html" title="A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.">Native_handle</a> or even <a class="el" href="structipc_1_1util_1_1Native__handle.html#a7194e8aaf9fc0109aad80222ae4ecb25" title="The native handle type. Much logic relies on this type being light-weight (fast to copy).">Native_handle::handle_t</a>, specifically for the boost.asio integration use case. If <em>not</em> integrating with boost.asio, <code>start_*ops()</code> is to be used without preceding it by <code>replace_event_wait_handles()</code>, and <code>hndl-&gt;native_handle()</code> is the only meaningful part of <code>*hndl</code>, with <code>.async_wait()</code> being meaningless and unused. Conversely, if integrating with boost.asio, <code>hndl-&gt;native_handle()</code> itself should not be required in your code, while <code>.async_wait()</code> is the only meaningful aspect of <code>*hndl</code>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="sync__io__fwd_8hpp_source.html#l00817">817</a> of file <a class="el" href="sync__io__fwd_8hpp_source.html">sync_io_fwd.hpp</a>.</p>

</div>
</div>
<a id="ac6973c71fc70c6d867b0f2255c642532" name="ac6973c71fc70c6d867b0f2255c642532"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ac6973c71fc70c6d867b0f2255c642532">&#9670;&nbsp;</a></span>Task_ptr</h2>

<div class="memitem">
<div class="memproto">
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532">ipc::util::sync_io::Task_ptr</a> = typedef boost::shared_ptr&lt;<a class="el" href="namespaceipc_1_1util.html#a31e67d3a017477a04b313927e2f2c733">Task</a>&gt;</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for ref-counted pointer to a <code>Function&lt;&gt;</code> that takes no arguments and returns nothing; in particular used for <code>on_active_ev_func</code> arg of <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">sync_io::Event_wait_func</a>. </p>
<h3>Rationale</h3>
<p >This is defined here because of its central role in <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">sync_io::Event_wait_func</a> (see that doc header).</p>
<p >Why wrap it in a smart pointer at all as opposed to passing around <code>Function&lt;&gt;</code>s as objects (particularly as arg to <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#aa0b9a3cc6bdc7dedbef4f9e06851aa24" title="In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...">Event_wait_func</a>)? Answer: Performance. Our <code><a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">sync_io</a></code> pattern is intended for the highly perf-conscious user, to the extent they'd forego the significantly easier to use async-I/O pattern just because that would involve involuntary (from the user's point of view) thread creation and context switching; copying or moving polymorphic functors, including all their captures, is an unnecessary expense.</p>
<p >In that case why <code>shared_ptr</code>, not <code>unique_ptr</code>, given that it adds potential ref-counting behind the scenes? Answer: <code>unique_ptr</code> would have been nice; however it is likely the user (and/or internal Flow-IPC code) will want to lambda-capture the wrapped <code>Task</code>, and capturing movable-but-not-copyable types like <code>unique_ptr</code> does not compile (as of C++17), even if one never copies the capturing lambda. One would need to upgrade to <code>shared_ptr</code> to capture, and that is annoying.</p>
<dl class="section note"><dt>Note</dt><dd>That said it is recommended that one <code>std::move()</code> any <a class="el" href="namespaceipc_1_1util_1_1sync__io.html#ac6973c71fc70c6d867b0f2255c642532" title="Short-hand for ref-counted pointer to a Function&lt;&gt; that takes no arguments and returns nothing; in pa...">Task_ptr</a> whenever possible, such as when capturing it in a lambda (e.g., <code>[task_ptr = std::move(task_ptr)</code>). This advice applies generally to all <code>shared_ptr</code> captures ("whenever possible" being important), but this is just a reminder. </dd></dl>

<p class="definition">Definition at line <a class="el" href="sync__io__fwd_8hpp_source.html#l00585">585</a> of file <a class="el" href="sync__io__fwd_8hpp_source.html">sync_io_fwd.hpp</a>.</p>

</div>
</div>
<h2 class="groupheader">Function Documentation</h2>
<a id="adef3ac3be5570b22492dd9214b4cb3da" name="adef3ac3be5570b22492dd9214b4cb3da"></a>
<h2 class="memtitle"><span class="permalink"><a href="#adef3ac3be5570b22492dd9214b4cb3da">&#9670;&nbsp;</a></span>operator&lt;&lt;()</h2>

<div class="memitem">
<div class="memproto">
      <table class="memname">
        <tr>
          <td class="memname">std::ostream &amp; ipc::util::sync_io::operator&lt;&lt; </td>
          <td>(</td>
          <td class="paramtype">std::ostream &amp;&#160;</td>
          <td class="paramname"><em>os</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html">Timer_event_emitter</a> &amp;&#160;</td>
          <td class="paramname"><em>val</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Prints string representation of the given <code><a class="el" href="classipc_1_1util_1_1sync__io_1_1Timer__event__emitter.html" title="An object of this type, used internally to implement sync_io-pattern objects that require timer event...">Timer_event_emitter</a></code> to the given <code>ostream</code>. </p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">os</td><td>Stream to which to write. </td></tr>
    <tr><td class="paramname">val</td><td>Object to serialize. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>os</code>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="timer__ev__emitter_8cpp_source.html#l00136">136</a> of file <a class="el" href="timer__ev__emitter_8cpp_source.html">timer_ev_emitter.cpp</a>.</p>

</div>
</div>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 11 2025 20:02:27 for Flow-IPC by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
